/*
 Xern Entity Relocation Network
 Copyright (C) 2010-2011 Ronie Salgado <roniesalg@gmail.com>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
*/

#ifndef XERN_OGRERENDERER_HPP
#define XERN_OGRERENDERER_HPP

#include <list>
#include <boost/weak_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <OgreRoot.h>
#include <OgreWindowEventUtilities.h>
#include "MyGUI_OgrePlatform.h"
#include "Xern/IParticleSystem.hpp"
#include "Xern/IRenderer.hpp"
#include "Xern/SharedSingleton.hpp"

namespace XernOgre
{
	using namespace Xern;

	class ShadowListener;
	class OgreLoader;
	class GeometryInstance;
	class OgreRenderer: public IRenderer, public Ogre::WindowEventListener,
		public Ogre::FrameListener, public SharedSingleton<OgreRenderer>,
		public boost::enable_shared_from_this<OgreRenderer>
	{
	public:
		OgreRenderer();
		~OgreRenderer();

		// Xern::IRenderer
		virtual void Initialize();
		virtual void Shutdown();

		virtual bool RenderFrame(float delta);

		virtual boost::shared_ptr<ISceneNode> CreateSceneNode();
		virtual boost::shared_ptr<ISceneNode> CreateRegionNode();
		virtual boost::shared_ptr<ISceneNode> CreateWorldNode();

		virtual boost::shared_ptr<ICamera> CreateCamera(const std::string &name);
		virtual void SetCurrentCamera(boost::shared_ptr<ICamera> camera);

		virtual boost::shared_ptr<IMaterial> CreateMaterial(const std::string &baseName);
		virtual boost::shared_ptr<ITexture> CreateTexture2D(int width, int height, ITexture::TextureFormat format, bool dynamic=false);
		virtual boost::shared_ptr<ITexture> CreateTexture2D(int width, int height, ITexture::TextureFormat format, size_t dataLen, const void *data, float gammaFactor=1.0f);

		virtual boost::shared_ptr<IGeometry> CreateGeometry(boost::shared_ptr<RegionMesh> mesh);
		virtual boost::shared_ptr<IGeometry> CreateGeometry(const std::string &meshfile, const std::string &group);
		virtual boost::shared_ptr<IGeometry> CreateGeometry(const std::string &name, const std::string &meshfile, const std::string &group);

		virtual boost::shared_ptr<IGeometry> CreateTerrainPlane(float width, float height, int mapWidth, int mapHeight, Vector3 planeNormal, bool normals);
		virtual boost::shared_ptr<IProceduralPrimitive> CreatePrimitive(int primWidth, int primHeight);

		virtual boost::shared_ptr<ILight> CreateLight(const std::string &name);
		virtual boost::shared_ptr<ILight> CreateLight();

		virtual void SetSkybox(boost::shared_ptr<IMaterial> material);
		virtual void SetSkybox(const std::string &material);

		virtual boost::shared_ptr<IParticleSystem> CreateParticleSystem(const std::string &templateName);

		std::string CreateEntityName();

		// Ogre::WindowEventListener
		virtual void windowResized(Ogre::RenderWindow* rw);
		virtual void windowClosed(Ogre::RenderWindow* rw);

		// Ogre::FrameListener
		virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);

		void RegisterAnimated(boost::shared_ptr<GeometryInstance> animated);

		Ogre::SceneManager *GetSceneManager();

	private:
		typedef std::list<boost::weak_ptr<GeometryInstance> > GeometryInstanceList;

		friend class OgreLoader;
		void SetupResources();
		void CreateNullRenderer();
		void SetVideoMode();
		void SetupLighting();
		void SetupCamera();

		Ogre::Root *root;
		Ogre::String pluginsConfig;
		Ogre::RenderWindow *renderWindow;
		Ogre::SceneManager *sceneManager;
		Ogre::Camera *globalCamera;
		Ogre::Camera *currentCamera;
		Ogre::Viewport *viewport;
		ShadowListener *shadowListener;
		MyGUI::OgrePlatform* myGuiOgre;
		int meshCounter;
		int materialCounter;
		int textureCounter;
		int entityCounter;
		int systemCounter;
		bool rendering;
		boost::shared_ptr<OgreLoader> ogreLoader;
		GeometryInstanceList animatedGeometry;
	};
};

#endif //XERN_BULLETPHYSICS_HPP
